home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Almathera Ten Pack 3: CDPD 3
/
Almathera Ten on Ten - Disc 3: CDPD3.iso
/
scope
/
076-100
/
scopedisk81
/
wkeys
/
wkeys.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-03-19
|
12KB
|
357 lines
/*
* wKeys.c Moves and activates windows and screens via keystrokes.
*
* Copyright (c) 1987,1988 by Davide P. Cervone
* You may use this code provided this copyright notice is left intact.
*/
#include <exec/types.h>
#include <libraries/dos.h>
#include <exec/io.h>
#include <exec/memory.h>
#include <exec/interrupts.h>
#include <devices/input.h>
#include <devices/inputevent.h>
#include "wKeys.h"
static char *program = "wKeys";
static int version = 2;
static char *date = "January 1988";
static char *author = "Copyright (c) 1987,1988 by Davide P. Cervone";
static int hversion = 0;
static char *PortName = "wKeysPort";
static char *handler = "L:wKeys-Handler"; /* the handler file */
#define HANDLER &(handler[2]) /* without the "L:" */
/*
* This is the structure that holds the handler information between calls
* to wKeys. We create a named, public message-port that points to
* an instance of this structure so that we can find this information
* when we are asked to remove the handler. The PortName is stored here
* (NamedPort->mp_Node.ln_Name uses this area for it's name). The other
* data are what we need in order to remove the handler and clean up properly.
*/
struct HandlerBlock
{
char *PortName; /* name of the public, named message-port */
struct Interrupt Handler; /* the handler added to the handler chain */
struct IntuitionBase *Ibase; /* an error if the handler can't be found */
struct LayersBase *Lbase; /* library base used by the handler */
long Segment; /* pointer from LoadSeg() */
struct HotKey *Keys; /* pointer to Key array */
struct MsgPort *ReplyPort; /* the reply port for CLOSE-WINDOW */
int KeyCount; /* size of Key array */
};
#define HANDLERINFOSIZE sizeof(struct HandlerBlock)
#define NAMESIZE (strlen(PortName)+1)
/*extern struct MsgPort *CreatePort();*/
extern struct IOStdReq *CreateStdIO();
extern struct MsgPort *FindPort(), *CreatePort();
extern APTR AllocMem();
extern long LoadSeg();
#define INTUITION_REV 0L
#define LAYERS_REV 0L
struct IntuitionBase *IntuitionBase = NULL;
struct LayersBase *LayersBase = NULL;
extern struct SysBase *SysBase;
struct MsgPort *InputPort = NULL; /* Port used to talk to Input.Device */
struct IOStdReq *InputBlock = NULL; /* request block used with Input.Device */
LONG InputDevice = 0; /* flag whether Input.Device is open */
struct MsgPort *NamedPort = NULL; /* holds info needed to remove handler */
struct MsgPort *ReplyPort = NULL; /* reply port for CLOSE-WINDOW */
struct HandlerBlock *HandlerInfo = NULL; /* holds info stored in NamedPort */
extern struct HotKeyItem *KeyList;
extern struct HotKey *KeyArray;
extern int KeyCount;
#define KEYARRAYSIZE (KeyCount*sizeof(struct HotKey))
extern void GetKeyArray();
/*
* DeleteNonSigPort()
*
* Deletes a message port with signal type PA_IGNORE. Based on
* DeletePort() from the exec support functions documented in the RKM
*/
void DeleteNonSigPort(thePort)
struct MsgPort *thePort;
{
if (thePort->mp_Node.ln_Name) RemPort(thePort);
thePort->mp_Node.ln_Type = 0xFF;
thePort->mp_MsgList.lh_Head = (struct Node *) -1;
FreeMem(thePort,(ULONG)sizeof(struct MsgPort));
}
/*
* CreateNonSigPort()
*
* Creates a message port with signal type PA_IGNORE. Based on
* CreatePort() from the exec support functions documented in the RKM.
*/
struct MsgPort *CreateNonSigPort(name,pri)
char *name;
BYTE pri;
{
struct MsgPort *thePort;
thePort = (struct MsgPort *)AllocMem((ULONG)sizeof(struct MsgPort),
MEMF_PUBLIC | MEMF_CLEAR);
if (thePort)
{
thePort->mp_Node.ln_Name = name;
thePort->mp_Node.ln_Pri = pri;
thePort->mp_Node.ln_Type = NT_MSGPORT;
thePort->mp_Flags = PA_IGNORE;
thePort->mp_SigBit = 0;
thePort->mp_SigTask = NULL;
if (name)
AddPort(thePort);
else
NewList(&(thePort->mp_MsgList));
}
return(thePort);
}
/*
* DoExit()
*
* General purpose exit routine. If 's' is not NULL, then print an
* error message with up to three parameters. Free any memory, close
* any open device, delete any ports, close any libraries, etc.
*/
void DoExit(s,x1,x2,x3)
char *s, *x1, *x2, *x3;
{
long status = RETURN_OK;
struct HotKeyItem *TempKey;
if (s != NULL)
{
printf(s,x1,x2,x3);
printf("\n");
status = RETURN_ERROR;
}
if (InputDevice) CloseDevice(InputBlock);
if (InputBlock) DeleteStdIO(InputBlock);
if (InputPort) DeletePort(InputPort);
if (NamedPort) DeleteNonSigPort(NamedPort);
if (ReplyPort) DeleteNonSigPort(ReplyPort);
if (HandlerInfo)
{
if (HandlerInfo->PortName) FreeMem(HandlerInfo->PortName,NAMESIZE);
FreeMem(HandlerInfo,HANDLERINFOSIZE);
}
if (KeyArray) FreeMem(KeyArray,KEYARRAYSIZE);
while (KeyList)
{
TempKey = KeyList;
KeyList = KeyList->Next;
FreeMem(TempKey,sizeof(*TempKey));
}
if (IntuitionBase) CloseLibrary(IntuitionBase);
if (LayersBase) CloseLibrary(LayersBase);
exit(status);
}
/*
* CheckLibOpen()
*
* General library open routine. It opens a library and sets a pointer
* to it. It checks that the library was openned successfully.
*/
static void CheckLibOpen(lib,name,rev)
APTR *lib;
char *name;
int rev;
{
extern APTR OpenLibrary();
if ((*lib = OpenLibrary(name,(LONG)rev)) == NULL)
DoExit("Can't open '%s'\n",name);
}
/*
* Macros that make memory allocation easier.
*/
#define NEW(s,var) (var = (struct s *)New("var",sizeof(struct s)))
#define NEWCHAR(var,s) (var = (char *)New("var",s))
/*
* New()
*
* Allocate public memory of a given size and set it to all zeros. If there
* is not enough memory, then exit with an error, otherwise return the
* pointer to the newly allocated memory.
*/
APTR New(name,size)
char *name;
int size;
{
APTR ptr;
if ((ptr = AllocMem(size,MEMF_PUBLIC | MEMF_CLEAR)) == NULL)
DoExit("Can't Get Memory for '%s'",name);
return(ptr);
}
/*
* TellInputDevice()
*
* Create a port and I/O block, and open the input device. Set up the
* I/O block to add or remove the input handler, and send the request
* to the input device. Finally, close the device and delete the
* I/O block and port.
*/
static void TellInputDevice(function)
int function;
{
long status;
if ((InputPort = CreatePort(0,0)) == NULL) DoExit("Can't Create Port");
if ((InputBlock = CreateStdIO(InputPort)) == NULL)
DoExit("Can't Create Standard IO Block");
InputDevice = (OpenDevice("input.device",0,InputBlock,0) == 0);
if (InputDevice == FALSE) DoExit("Can't Open 'input.device'");
InputBlock->io_Command = (long) function;
InputBlock->io_Data = (APTR) &(HandlerInfo->Handler);
if (status = DoIO(InputBlock)) DoExit("Error from DoIO: %ld",status);
CloseDevice(InputBlock);
DeleteStdIO(InputBlock);
DeletePort(InputPort);
}
/*
* CreateHandler()
*
* Open the libraries needed by the input handler and store their locations
* in the HandlerInfo structure (so we can close them later). Try to
* LoadSeg() the handler. If it is not in the current directory, try the
* L: directory. Exit with an error if the handler can't be found.
* Convert the segment pointer into a pointer to the Setup() routine (the
* first routine in the handler executable). Call Setup() and pass it
* the pointers to the libraries that it will need to use. Setup() returns
* a pointer to the actual handler routine that should be added into the
* input handler chain. Store this in the HandlerInfo structure so we
* can use it to remove the handler later. Set the handler priority to
* 51 so that it is ahead of Intuition.
*
* Finally, add the handler in the chain and tell the user that the
* handler has been installed.
*/
static void CreateHandler()
{
long (*Setup)();
CheckLibOpen(&IntuitionBase,"intuition.library",INTUITION_REV);
CheckLibOpen(&LayersBase,"layers.library",LAYERS_REV);
HandlerInfo->Ibase = IntuitionBase;
HandlerInfo->Lbase = LayersBase;
if ((HandlerInfo->Segment = LoadSeg(HANDLER)) == NULL)
if ((HandlerInfo->Segment = LoadSeg(handler)) == NULL)
DoExit("Can't Load '%s'",handler);
Setup = (long (*)()) ((HandlerInfo->Segment << 2) + 4);
HandlerInfo->Handler.is_Code =
(void (*)()) ((*Setup)(IntuitionBase,LayersBase,SysBase,
KeyArray,KeyCount,ReplyPort,&hversion));
HandlerInfo->Handler.is_Node.ln_Pri = 51;
HandlerInfo->Keys = KeyArray;
HandlerInfo->KeyCount = KeyCount;
HandlerInfo->ReplyPort = ReplyPort;
TellInputDevice(IND_ADDHANDLER);
printf("%s v%d.%d (%s) Installed\n",program,version,hversion,date);
}
/*
* Delete Handler()
*
* Retreive the library pointers from the HandlerInfo structure, where
* we stored them when we originally installed the handler, then remove
* the handler from the input handler chain. Tell the user that the
* handler is gone, and then close the libraries that are no longer needed.
*/
static void DeleteHandler()
{
IntuitionBase = HandlerInfo->Ibase;
LayersBase = HandlerInfo->Lbase;
KeyArray = HandlerInfo->Keys;
KeyCount = HandlerInfo->KeyCount;
ReplyPort = HandlerInfo->ReplyPort;
TellInputDevice(IND_REMHANDLER);
UnLoadSeg(HandlerInfo->Segment);
printf("%s Removed\n",program);
FreeMem(KeyArray,KEYARRAYSIZE);
CloseLibrary(IntuitionBase);
CloseLibrary(LayersBase);
}
/*
* main()
*
* Check if a message port with our name already exists.
* If not, then the handler is not already installed, so:
* Allocate a new HandlerInfo structure and initialize the port name.
* Create a public, named message-port (we will look for this the next
* time wKeys is called).
* Make the message port point to the HandlerInfo structure so we
* can use it later when the user asks us to remove the handler.
* Note that the port is not actually used for putting and getting
* messages, so the Task field is never used, so we can take it for
* our own uses.
* Get a port to use as a reply port for CLOSE-WINDOW intuimessages.
* Finally, add the input handler into the chain.
* Otherwise, the port exists, so wKeys already is installed:
* Retreive the HandlerInfo poiner from the port, and remove the
* handler from the input handler chain.
* Free the memory used by the HandlerInfo, and delete the message ports.
*/
void main(argc,argv)
int argc;
char **argv;
{
NamedPort = FindPort(PortName);
if (NamedPort == NULL)
{
NEW(HandlerBlock,HandlerInfo);
NEWCHAR(HandlerInfo->PortName,NAMESIZE);
strcpy(HandlerInfo->PortName,PortName);
if ((NamedPort = CreateNonSigPort(HandlerInfo->PortName,0)) == NULL)
DoExit("Can't Create Message Port '%s'",PortName);
if ((ReplyPort = CreateNonSigPort(NULL,0)) == NULL)
DoExit("Can't Create Reply Port");
NamedPort->mp_SigTask = (struct Task *)HandlerInfo;
GetKeyArray(argc,argv);
CreateHandler();
} else {
HandlerInfo = (struct HandlerBlock *)(NamedPort->mp_SigTask);
DeleteHandler();
FreeMem(HandlerInfo->PortName,NAMESIZE);
FreeMem(HandlerInfo,HANDLERINFOSIZE);
DeleteNonSigPort(ReplyPort);
DeleteNonSigPort(NamedPort);
}
}